package com.example.administrator.zhongyichou.net.core;

import android.app.Activity;
import android.support.annotation.NonNull;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.example.administrator.zhongyichou.base.MyApplication;
import com.example.administrator.zhongyichou.net.NetConfig;
import com.example.administrator.zhongyichou.net.listener.ResultListener;
import com.example.administrator.zhongyichou.net.protocol.GsonBaseProtocol;
import com.example.administrator.zhongyichou.utils.LogUtils;
import com.example.administrator.zhongyichou.utils.NetworkUtils;
import com.example.administrator.zhongyichou.utils.ToastUtil;
import com.example.administrator.zhongyichou.view.LoadingDialog;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;

/**
 * Created by lichenyu on 2017/8/10.
 */

public abstract class HttpLoader {
    private static final String TAG = "HttpLoader";
    public Class parseClass;//创建需要被解析的协议类,
    private Retrofit mRetrofit;                        //创建Retrofit的引用
    private Activity activity;
    private boolean isShowDialog = false;
    private String dialogContent = "正在加载";
    private LoadingDialog loadingDialog;

    /**
     * 构造传递监听的接口，以及需要被解析的字节码文件
     *
     * @param parseClass
     */
    public HttpLoader(Class<? extends GsonBaseProtocol> parseClass) {

        this.parseClass = parseClass;
        //构建retrofit
        mRetrofit = buildRetrofit();
    }

    /**
     * 具体构建Observable要子类自己去实现
     * 需要自己定义被观察者
     *
     * @param mRetrofit
     * @return
     */
    public abstract Observable<ResponseBody> structureObservable(Retrofit mRetrofit);

    /**
     * 集体执行逻辑
     *
     * @param mResultListener 结果监听
     */
    public void executor(final ResultListener mResultListener) {
        if (isShowDialog && loadingDialog != null) {
            loadingDialog.setText(dialogContent);
            loadingDialog.show();
        }
        if (!NetworkUtils.checkNetwork(MyApplication.getContext())) {//如果没有网络
            mResultListener.notNet();                    //没有网络就显示错误界面
            if (loadingDialog != null)
                loadingDialog.dismiss();
            return;
        }

        // Retrofit 承载类 被观察者
        Observable<ResponseBody> mObservable = structureObservable(mRetrofit);  //构建被观察者,并且将Retrofit对象作为形参
        mObservable.subscribeOn(Schedulers.io())                                //订阅者在子线程中运行
                //定义了这个说明我们的 observable 观察者在主线程中执行
                .observeOn(AndroidSchedulers.mainThread())                      //观察者在主线程中运行
                .subscribe(new Observer<ResponseBody>() {                       //通过订阅将观察者和被观察者联系在一起
                    //数据请求错误
                    @Override
                    public void onError(Throwable e) {
                        e.printStackTrace();
                        mResultListener.requestError();
                        if (loadingDialog != null)
                            loadingDialog.dismiss();
                        ToastUtil.showToast("请求失败");
                        LogUtils.e(TAG, e.getMessage());
                    }

                    @Override
                    public void onComplete() {

                    }

                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    /**
                     * 以onNext()方法作为一次成功请求的调用
                     * @param mResponseBody
                     */
                    @Override
                    public void onNext(ResponseBody mResponseBody) {
                        try {
                            dispatchResult(mResponseBody, mResultListener);     //成功之后就请求结果数据
                            if (loadingDialog != null)
                                loadingDialog.dismiss();
                        } catch (IOException e) {
                            e.printStackTrace();
                            mResultListener.error("数据解析失败");
                            LogUtils.e(e);
                        } catch (ClassCastException e) {
                            e.printStackTrace();
                            mResultListener.error("类型转换异常");
                            LogUtils.e(e);
                        } catch (NullPointerException e) {
                            e.printStackTrace();
                            mResultListener.error("空指针异常");
                            LogUtils.e(e);
                        } catch (JSONException e) {
                            e.printStackTrace();
                            mResultListener.error("数据解析异常");
                            LogUtils.e(e);
                        }
                    }
                });
    }


    /**
     * 构建Retrofit
     *
     * @return
     */
    public static int DEFAULT_TIMEOUT = 30;

    private Retrofit buildRetrofit() {
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                .build();
        //Retrofit的构建,
        return new Retrofit.Builder()
                .baseUrl(NetConfig.BASE_URL)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())   //将Retrofit转换成Rxjava可用的适配类
//                .addConverterFactory(GsonConverterFactory.create())
                .client(okHttpClient)
                .build();
    }

    /**
     * 处理服务器返回的数据
     * <p>
     * 事先抛出一些常见异常，防止服务器数据不正确时程序崩溃
     *
     * @param mResponseBody
     * @param mResultListener
     */
    private void dispatchResult(ResponseBody mResponseBody, @NonNull ResultListener mResultListener) throws IOException, NullPointerException, ClassCastException, JSONException {
        String resultString = mResponseBody.string();           //将请求到的json数据装换成字符串
        LogUtils.e(TAG, "返回数据:" + resultString);
        //取出第二层的数据
        JSONObject jsonObject = JSON.parseObject(resultString);
//        GsonBaseProtocol gsonBaseProtocol = (GsonBaseProtocol) JsonUtil.parseJsonToBean(resultString, parseClass); //解析json数据
        GsonBaseProtocol gsonBaseProtocol = (GsonBaseProtocol) JSONObject.parseObject(jsonObject.getString(getResponseUrl()), parseClass); //解析json数据

        if (gsonBaseProtocol.getCode() == 0) {
            mResultListener.success(gsonBaseProtocol);              //调用成功的方法
        } else {//请求失败
            mResultListener.error(gsonBaseProtocol.getMsg());
            if (gsonBaseProtocol.getMsg() != null && !"".equals(gsonBaseProtocol.getMsg()))
                ToastUtil.showToast(gsonBaseProtocol.getMsg());
        }
        LogUtils.e(TAG, gsonBaseProtocol.toString());
    }

    public void showDialog(Activity activity, boolean isShowDialog, String dialogContent) {
        if (loadingDialog == null) {
            loadingDialog = new LoadingDialog(activity);
        }
        this.activity = activity;
        this.isShowDialog = isShowDialog;
        this.dialogContent = dialogContent;
    }

    public void showDialog(Activity activity, boolean isShowDialog) {
        if (loadingDialog == null) {
            loadingDialog = new LoadingDialog(activity);

        }
        this.activity = activity;
        this.isShowDialog = isShowDialog;
    }

    //接口返回参数最外层的key值，每个接口都不一样 ,需要请求打断点拿到在设置进去解析，一个字坑。
    private String responseUrl;

    public void setResponseUrl(String responseUrl) {
        this.responseUrl = responseUrl;
    }

    public String getResponseUrl() {
        return responseUrl;
    }
}



